{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Logic Programming for AI.ipynb",
      "provenance": [],
      "authorship_tag": "ABX9TyOw/51aWgZ+Xii733W4Oprw",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/rjrahul24/ai-with-python-series/blob/main/03.%20Logic%20Programming%20for%20AI/Code/Logic_Programming_for_AI.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Re9u-xNmowwr"
      },
      "source": [
        "# Run the below command to install kanren. \n",
        "# It does not come pre-installed with the Anaconda distribution of Jupyter Notebook. You will see an installation like below."
      ],
      "execution_count": 1,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "JvuLhJcJo2uO",
        "outputId": "feae8a77-47aa-4a9b-d77a-7fb250d108e2"
      },
      "source": [
        "pip install kanren"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Collecting kanren\n",
            "  Downloading kanren-0.2.3.tar.gz (23 kB)\n",
            "Requirement already satisfied: toolz in /usr/local/lib/python3.7/dist-packages (from kanren) (0.11.1)\n",
            "Collecting multipledispatch\n",
            "  Downloading multipledispatch-0.6.0-py3-none-any.whl (11 kB)\n",
            "Collecting unification\n",
            "  Downloading unification-0.2.2-py2.py3-none-any.whl (10 kB)\n",
            "Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from multipledispatch->kanren) (1.15.0)\n",
            "Building wheels for collected packages: kanren\n",
            "  Building wheel for kanren (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Created wheel for kanren: filename=kanren-0.2.3-py3-none-any.whl size=15871 sha256=408e9a8fb9b926671951ce9433721cf28699aa23187edae2dfd1691c807a1904\n",
            "  Stored in directory: /root/.cache/pip/wheels/26/cb/32/093b860ec60752641d76d706af25a175597cf56e152282cbbe\n",
            "Successfully built kanren\n",
            "Installing collected packages: multipledispatch, unification, kanren\n",
            "Successfully installed kanren-0.2.3 multipledispatch-0.6.0 unification-0.2.2\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Uik2kp8qo88R"
      },
      "source": [
        "# Once kanren is installed to the Jupyter Notebook kernel, run the below command to install sympy. \n",
        "# All required components of the sympy collection will get installed"
      ],
      "execution_count": 3,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "wsugu3HKpC5y",
        "outputId": "66114b75-0ef8-4f7a-d68f-b0454ee7a8d1"
      },
      "source": [
        "pip install sympy"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Requirement already satisfied: sympy in /usr/local/lib/python3.7/dist-packages (1.7.1)\n",
            "Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy) (1.2.1)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qm4DazkLpKX0"
      },
      "source": [
        "**Evaluating Mathematical Idioms using Logic Programming**\n",
        "\n",
        "Algorithms are nothing but implementation of logic and control. Similarly, when the logic runs a mathematical function, we call it a mathematical expression. These expressions are the inputs we give to the program, based on which the program understands the rules that are present in the logic. Based on the understanding of these rules, future expressions can also be evaluated. Let us see an implementation of Logic Programming to evaluate mathematical expressions:\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WJ2Nw8udpEk0"
      },
      "source": [
        "# Import the necessary functions from the kanren library\n",
        "from kanren import run, var, fact\n",
        "from kanren.assoccomm import eq_assoccomm as eq\n",
        "from kanren.assoccomm import commutative, associative\n",
        "\n",
        "# Define values that will undertake the addition and multiplication operations\n",
        "addition = 'add'\n",
        "multiplication = 'mul'\n",
        "\n",
        "# Define facts and properties of each operation\n",
        "fact(commutative, multiplication)\n",
        "fact(commutative, addition)\n",
        "fact(associative, multiplication)\n",
        "fact(associative, addition)\n",
        "\n",
        "# Declare the variables that are going to form the expression\n",
        "var_x, var_y, var_z = var('var_x'), var('var_y'), var('var_z')\n",
        "\n",
        "# Build the correct pattern that the program needs to learn\n",
        "match_pattern = (addition, (multiplication, 4, var_x, var_y), var_y, (multiplication, 6, var_z))\n",
        "match_pattern = (addition, (multiplication, 3, 4), (multiplication, (addition, 1, (multiplication, 2, 4)),2))\n",
        "\n",
        "# Build 3 distinct expressions to test if the function has learnt\n",
        "test_expression_one = (addition, (multiplication, (addition, 1 , (multiplication, 2, var_x )), var_y) ,(multiplication, 3, var_z )) \n",
        "test_expression_two = (addition, (multiplication, var_z, 3), (multiplication, var_y, (addition, (multiplication, 2, var_x), 1)))\n",
        "test_expression_three = (addition  , (addition, (multiplication, (multiplication, 2, var_x), var_y), var_y), (multiplication, 3, var_z))"
      ],
      "execution_count": 5,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "DkruLwbppciL",
        "outputId": "7abe1ebb-ed16-4cd7-d2c6-8c102c31e247"
      },
      "source": [
        "# Test the evaluations of the expression on the test expressions\n",
        "run(0,(var_x,var_y,var_z),eq(test_expression_one,match_pattern))"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "((4, 2, 4),)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 7
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "TdyxmA5OpkQr",
        "outputId": "f4780171-0567-4f5b-d31b-a2323e24959a"
      },
      "source": [
        "run(0,(var_x,var_y,var_z),eq(test_expression_two,match_pattern))"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "((4, 2, 4),)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "TO07WYM7pqXe",
        "outputId": "f2798634-9b67-4c34-8d3a-4d95df8db127"
      },
      "source": [
        "print(run(0,(var_x,var_y,var_z),eq(test_expression_three,match_pattern)))"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "()\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bjCG8n2Xpsz0"
      },
      "source": [
        "# Since the first two expressions satisfy the expression above, they return the values of individual variables. \n",
        "# The third expression is structurally different and therefore does not match."
      ],
      "execution_count": 10,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "xBeboBjfpxet",
        "outputId": "3ae97ff2-cba5-46fd-d52d-31b408ddaf71"
      },
      "source": [
        "# Running Mathematical Evaluations using SymPy\n",
        "import math\n",
        "import sympy\n",
        "\n",
        "print (math.sqrt(8))"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "2.8284271247461903\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ZdJMZwp8p3Vf",
        "outputId": "dc8359fb-343a-491b-9156-e2f4edee3f7b"
      },
      "source": [
        "# Although the Math Square Root function gives an output for the Square Root of 8. \n",
        "# We know this is not accurate since the square root of 8 is a recursive, non-ending real number\n",
        "print (sympy.sqrt(3))"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "sqrt(3)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "s3RVCSP-p-tN"
      },
      "source": [
        "# Sympy on the other hand, symbolizes the output and shows it as root of 3\n",
        "# In case of actual square roots like 9, SymPy gives the correct result and not a symbolic answer"
      ],
      "execution_count": 13,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Pq22Um2HqABs"
      },
      "source": [
        "# Import the necessary libraries for running the Prime Number function\n",
        "from kanren import membero, isvar, run\n",
        "from kanren.core import goaleval, condeseq, success, fail, eq, var\n",
        "from sympy.ntheory.generate import isprime, prime\n",
        "import itertools as iter_one\n",
        "\n",
        "# Defining a function to build the expression\n",
        "def exp_prime (input_num):\n",
        "  if isvar(input_num):\n",
        "    return condeseq([(eq, input_num, x)] for x in map(prime, iter_one.count(1)))\n",
        "  else:\n",
        "      return success if isprime (input_num) else fail"
      ],
      "execution_count": 15,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "1U_X36pKqH6L",
        "outputId": "5d0a3934-b539-4db4-9d29-a0f9cefbd09c"
      },
      "source": [
        "# Variable to use\n",
        "n_test = var() \n",
        "set(run(0, n_test,(membero, n_test,(12,14,15,19,21,20,22,29,23,30,41,44,62,52,65,85)),( exp_prime, n_test)))"
      ],
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{19, 23, 29, 41}"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 16
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "EhnQr7NuqUOf",
        "outputId": "d25baa1f-56d6-4c25-d2dc-60f9af3566f7"
      },
      "source": [
        "run(7, n_test, exp_prime( n_test ) )"
      ],
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(2, 3, 5, 7, 11, 13, 17)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 17
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "0WkBo0OQqVtn"
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}